package com.qdlc.p2p.biz.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;

import org.apache.log4j.Logger;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import com.qdlc.p2p.biz.service.AccountService;
import com.qdlc.p2p.biz.service.InterestService;
import com.qdlc.p2p.biz.service.RateInterestService;
import com.qdlc.p2p.common.constant.GeneralAccountType;
import com.qdlc.p2p.common.constant.Global;
import com.qdlc.p2p.common.constant.LogTplNid;
import com.qdlc.p2p.common.constant.RateInterestStatus;
import com.qdlc.p2p.common.constant.UseRateLogStatus;
import com.qdlc.p2p.common.util.BigDecimalUtil;
import com.qdlc.p2p.common.util.CollectionUtils;
import com.qdlc.p2p.common.util.DateUtil;
import com.qdlc.p2p.common.util.LogFactory;
import com.qdlc.p2p.dal.common.SystemConfigHelper;
import com.qdlc.p2p.dal.dao.*;
import com.qdlc.p2p.dal.dto.*;
import com.qdlc.p2p.dal.model.interest.EachPlan;
import com.qdlc.p2p.dal.model.interest.InterestCalculator;
import com.qdlc.p2p.dal.util.SystemConfigs;

@Repository("rateInterestService")
@Transactional
public class RateInterestServiceImpl implements RateInterestService {

    private static Logger logger = Logger.getLogger(RateInterestServiceImpl.class);

    /** 交易log */
    private static Logger tradeLogger = LogFactory.TRADE_LOGGER;

    private static final String WEB_URL = SystemConfigHelper.getValue(SystemConfigHelper.Nid.WEB_URL);

    private static final long ADMIN_ID = SystemConfigHelper.getLongValue(SystemConfigHelper.Nid.ADMIN_ACCOUNT);

    @Resource
    private RateInterestDao rateInterestDao;

    @Resource
    private BorrowCollectionDao borrowCollectionDao;

    @Resource
    private UpRateCollectionDao upRateCollectionDao;

    @Resource
    private UseRateLogDao useRateLogDao;

    @Resource
    private BorrowTenderDao borrowTenderDao;

    @Resource
    private BorrowDao borrowDao;

    @Resource
    private UserDao userDao;

    @Resource
    private InterestService interestService;

    @Resource
    private AccountService accountService;

    @Override
    public void tenderUseRateInte(BorrowTender tender, long rateInteId) {
        if (tender != null && rateInteId > 0) {
            RateInterest rateInterest = rateInterestDao.getRateInterestById(rateInteId);
            if (null == rateInterest) {
                logger.info("当前加息券未获取到---id>" + rateInteId);
                return;
            }
            if (rateInterest.getStatus() != 0) {
                logger.info("当前加息券状态不可用--->" + rateInterest.getStatus() + ";inteId-->" + rateInterest.getId());
                return;
            }

            //添加加息券使用记录
            User tenderUser = tender.getUser();
            Borrow borrow = tender.getBorrow();
            UseRateLog rateLog = new UseRateLog();
            rateLog.setBorrowId(borrow.getId());
            rateLog.setRateId(rateInteId);
            rateLog.setTenderId(tender.getId());
            rateLog.setUseTime(DateUtil.getNow());
            rateLog.setUpApr(rateInterest.getUpApr());
            rateLog.setNewApr(BigDecimalUtil.add(borrow.getApr(), rateInterest.getUpApr()));
            rateLog.setUserId(tenderUser.getUserId());
            useRateLogDao.save(rateLog);
            //更新加息券信息
            rateInterest.setStatus(1);
            rateInterest.setUseTime(DateUtil.getNow());
            rateInterestDao.update(rateInterest);
        }
    }

    // 满标复审，处理加息券相关业务
    @Override
    public void borrowSuccessDoRate(long tenderId, String logType) {
        UseRateLog useRateLog = useRateLogDao.getRateLogByTenderId(tenderId);
        if (null == useRateLog
                || UseRateLogStatus.NORMAL != useRateLog.getStatus()) {
            logger.info("加息券记录不存在或者加息券所属标已取消, tenderId= " + tenderId);
            return;
        }
        //获取tender
        BorrowTender tender = borrowTenderDao.find(tenderId);
        //获取当前tender的所有待收记录
        List<BorrowCollection> collectionList = borrowCollectionDao.getCollectionByTender(tenderId);
        useRateInterest(useRateLog.getRateId(), tender, collectionList, useRateLog, logType);
    }

    // 处理加息券所产生的待收相关数据
    @Override
    public void useRateInterest(long rateInterestId, BorrowTender tender, List<BorrowCollection> collectionList,
                                UseRateLog useRateLog, String logType) {
        RateInterest rateInterest = rateInterestDao.find(rateInterestId);
        if (null == rateInterest) {
            logger.info("获取的加息券不存在, rateInterestId = " + rateInterestId);
            return;
        }
        //根据新的投标利率，计算出每一起所获取的利息，以及所有的待收利息总和
        List<BorrowCollection> oldCollection = collectionList;

        Borrow borrow = tender.getBorrow();
        double newApr = BigDecimalUtil.add(borrow.getApr(), rateInterest.getUpApr()) / 100;
        //获取计算器类型
        InterestCalculator ic = interestService.interestCalculator(borrow.getStyle(), tender.getAccount(),
                newApr, borrow.getBorrowTimeType(), borrow.getTimeLimit());
        List<EachPlan> eachPlanList = ic.getEachPlanList();//获取新利息的每一期还款详情

        //根据新投标利率，计算出新的每一期待收利息记录，将每一期利息差值保存到数据库中
        double newAprTotalInterest = BigDecimalUtil.sub(ic.repayTotal(), tender.getAccount()); //新投标利率所获得利息总和
        double newInterest = BigDecimalUtil.sub(newAprTotalInterest, tender.getInterest());
        double totalInterest = 0; //新利息总额
        List<UpRateCollection> upCollectionList = new ArrayList<UpRateCollection>();
        //根据原始待收记录，计算使用加息券后，每一期利息差额
        for (int j = 0; j < oldCollection.size(); j++) {
            BorrowCollection borrowCollection = oldCollection.get(j);
            EachPlan each = eachPlanList.get(j);
            UpRateCollection upCollection = new UpRateCollection();
            upCollection.setBorrowId(borrow.getId());
            upCollection.setCollectionId(borrowCollection.getId()); //待收id
            upCollection.setOldInterest(borrowCollection.getInterest());  //原始利率利息
            upCollection.setNewInterest(each.getInterest());  //设置产生的新利息
            upCollection.setPeriod(borrowCollection.getPeriod());  //设置期数
            upCollection.setWebPayMoney(0);
            upCollection.setUserId(borrowCollection.getUser().getUserId());
            upCollection.setDifferenceInterest(BigDecimalUtil.sub(each.getInterest(), borrowCollection.getInterest()));  //设置利息差值
            upCollection.setRepaymentTime(borrowCollection.getRepaymentTime());
            if (j == eachPlanList.size() - 1) {  //最后一期做差值
                double different = BigDecimalUtil.sub(newAprTotalInterest, totalInterest);
                upCollection.setNewInterest(different);
                upCollection.setDifferenceInterest(BigDecimalUtil.sub(different, borrowCollection.getInterest()));  //设置利息差值
            }
            totalInterest = BigDecimalUtil.add(totalInterest, each.getInterest());
            upCollection.setStatus(0);
            upCollectionList.add(upCollection);
        }

        //保存每一期与原始待收相对于的新的待收利息记录
        upRateCollectionDao.save(upCollectionList);
        //更新红包使用记录中新待还利息
        useRateLog.setUpInterest(newAprTotalInterest);
        useRateLogDao.update(useRateLog);

        // 更新用户资金和添加加息券预计待收收益资金记录
        Global.setTransfer(LogTplNid.LOG_TPL_KEY, logType);
        Global.setTransfer("web_url", WEB_URL);
        Global.setTransfer("borrow", borrow);
        Global.setTransfer("newInterest", newInterest);
        long tenderUserId = tender.getUser().getUserId();
        tradeLogger.info(String.format("用户ID[%d] 使用加息券[%d] 加息金额为[%f]", tenderUserId, rateInterestId, newInterest));
        accountService.addCollectionAndTotal(tenderUserId, GeneralAccountType.PLATFORM, newInterest);
    }

    // 还款处理加息券业务
    @Override
    public void repayWebPayUpInterest(long collectionId, String logType) {

        //获得使用加息券后，对应每个collection产生的额外利息
        UpRateCollection upCollection = upRateCollectionDao.getUpRateCollectionByCId(collectionId);
        if (null == upCollection) {
            logger.info("此待收没有相应的加息记录：id--->" + collectionId);
            return;
        }
        logger.info("开始处理待收加息-collectionId-->" + collectionId + ",期数：" + upCollection.getPeriod() + "加息券业务");
        Borrow borrow = borrowDao.find(upCollection.getBorrowId());
        //处理加息部分每一期的待收额外收益,加息部分收益由平台垫付
        User user = userDao.find(upCollection.getUserId());  //获取加息投资用户
        double upInterest = upCollection.getDifferenceInterest();  //平台垫付加息收益
        //更新用户资金
        Global.setTransfer(LogTplNid.LOG_TPL_KEY, logType);
        Global.setTransfer("borrow", borrow);
        Global.setTransfer("money", upInterest);
        accountService.revokeCapital(user.getUserId(), SystemConfigs.ADMIN_ID, upInterest);

        //更新加息券额外收益还款状态
        upCollection.setStatus(1);
        upCollection.setRepaymentYesTime(DateUtil.getNow());
        upCollection.setWebPayMoney(upInterest);
        upRateCollectionDao.update(upCollection);

        logger.info("加息券处理，待收id--->" + collectionId + ",期数：" + upCollection.getPeriod() + "处理完毕");
    }

    // 流标处理加息券业务
    @Override
    public void borrowFailDoRate(long borrowId) {
        List<UseRateLog> useLogList = useRateLogDao.getUseRateLogByBorrowId(borrowId);
        if (!CollectionUtils.isNotNullOrEmpty(useLogList)) {
            logger.info("该借款没有使用加息券投资的相关记录，不需要处理加息券相关业务……………………borrowid：" + borrowId);
            return;
        }
        logger.info("开始处理流标操作相关的加息券业务：borrowid：" + borrowId);
        //流标更新加息券有效时间算法（流标时间 - 投标使用日期=已使用天数，红包原始结束日期 +已使用天数 = 新结束日期）
        for (UseRateLog useRateLog : useLogList) {
            Date nowDate = DateUtil.getNow();
            int useDay = DateUtil.daysBetween(useRateLog.getUseTime(), nowDate); //计算加息券投标后使用的天数
            //计算新的加息券到期日期
            RateInterest rateInte = rateInterestDao.find(useRateLog.getRateId());
            Date newDate = DateUtil.rollDay(rateInte.getEndTime(), useDay);//延长加息券有效期
            rateInte.setEndTime(newDate);
            rateInte.setStatus(RateInterestStatus.NORMAL);//重置加息券状态
            rateInterestDao.update(rateInte);
            useRateLog.setStatus(UseRateLogStatus.CANCEL);//更新加息券使用状态，撤销：
            useRateLogDao.update(useRateLog);
        }
        logger.info("流标加息券相关业务处理完毕，borrowid：" + borrowId);
    }

    @Override
    public double getUpRateInterestByCollectionId(long collectionId) {
        return upRateCollectionDao.getUpRateInterestByCollectionId(collectionId);
    }

    @Override
    public List<Object[]> getRateCollectionInterest(User user, String date) {
        return upRateCollectionDao.getRateCollectionInterest(user, date);
    }
}
